package com.mall.b2c.controller;

import com.alibaba.fastjson.JSONObject;
import com.mall.b2c.bean.MemberBean;
import com.mall.b2c.hessian.MemberHessian;
import com.mall.b2c.util.SerialNumberUtil;
import com.mall.common.bean.Message;
import com.mall.common.exception.NoticeException;
import com.mall.common.service.MyCaptchaService;
import com.mall.common.util.AppContext;
import com.mall.common.util.ResponseUtils;
import com.mall.common.validation.annotation.RequiredStringValidator;
import com.mall.common.validation.annotation.Validations;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import static com.mall.b2c.Constants.REDIS_FORGET_SMS_PREFIX;
import static com.mall.b2c.Constants.SMS_RESEND_TIME;

/**
 * 找回密码
 * Created by lzx on 2015/4/28.
 */
@Controller("b2cRecoveryController")
@RequestMapping("/forget")
public class RecoveryController extends BaseController{

    @Resource
    private MemberHessian memberHessian;
    @Resource
    private MyCaptchaService captchaService;
    @Resource
    private RedisTemplate<String, String> redisTemplate;

    @RequestMapping(value = "/index", method = RequestMethod.GET)
    public String step1(Model model){
        String captchaId = UUID.randomUUID().toString();
        model.addAttribute("captchaId", captchaId);
        return "/forget/step1";
    }

    /**
     * 验证用户名
     * @param captchaId
     * @param captcha
     * @param username
     * @return
     */
    @Validations(
        requiredStrings = {
                @RequiredStringValidator(fieldName="username",message="请输入用户名"),
                @RequiredStringValidator(fieldName="captcha",message="请输入验证码"),
                @RequiredStringValidator(fieldName="captchaId",message="验证码错误")
        }
    )
    @RequestMapping(value = "/checkMember", method = RequestMethod.POST)
    public String checkUsername(String captchaId, String captcha, String username, HttpSession session, HttpServletResponse response){
        if (!captchaService.isValid(captchaId, captcha)) {
           throw new NoticeException("验证码错误");
        }
        MemberBean member = jsonToObj(memberHessian.getMemberInfo(null, username), MemberBean.class);
        if(member == null){
           throw new NoticeException("用户名不存在");
        }
        String token = SerialNumberUtil.buildTokenSn();
        String email = member.getEmail();
        String mobile = member.getMobile();
        session.setAttribute(token, new String[]{String.valueOf(member.getId()), email, mobile});
        return ResponseUtils.renderJSON(Message.success(token),response);
    }

    @RequestMapping(value = "/step2", method = RequestMethod.GET)
    public String step2(String token, Model model){
        Object obj = AppContext.getSessionAttr(token);
        if(obj == null){
            return "redirect:index.jhtml";
        }
        String[] memberInfo = (String[]) obj;
        String captchaId = UUID.randomUUID().toString();
        model.addAttribute("captchaId", captchaId);
        model.addAttribute("token", token);
        if(StringUtils.isNotBlank(memberInfo[1])) {
            String[] strs = memberInfo[1].split("@");
            model.addAttribute("email",  strs[0].substring(0, 2) + "***@" + strs[1]);
        }
        if(StringUtils.isNotBlank(memberInfo[2])) {
            model.addAttribute("mobile", memberInfo[2].substring(0, 3) + "*****" + memberInfo[2].substring(8));
        }
        return "/forget/step2";
    }

    /**
     * 发送邮箱验证码
     * @param token
     * @return
     */
    @RequestMapping(value = "/sendEmail.jhtml", method = RequestMethod.POST)
    public String sendToEmail(String token, HttpServletResponse response){
        Object obj = AppContext.getSessionAttr(token);
        if(obj == null){
            return ResponseUtils.renderJSON(errorMessage, response);
        }
        String[] memberInfo = (String[]) obj;
        memberHessian.sendEmail(memberInfo[1], Long.valueOf(memberInfo[0]), 2);
        return ResponseUtils.renderJSON(Message.success(token), response);
    }

    /**
     * 验证邮箱
     * @return
     */
    @RequestMapping(value = "/verifyEmail.jhtml", method = RequestMethod.GET)
    public String verifyEmailCode(String key, HttpSession session){
        MemberBean member = jsonToObj(memberHessian.recovery(key), MemberBean.class);
        if(member == null){
            throw new NoticeException("用户不存在");
        }
        session.setAttribute(key, member.getId());
        return "redirect:reset.jhtml?token=" + key;
    }



    @RequestMapping(value = "/step3", method = RequestMethod.GET)
    public String step3(String token ,Model model){
        Object obj = AppContext.getSessionAttr(token);
        if(obj == null){
            return "redirect:index.jhtml";
        }
        String[] memberInfo = (String[]) obj;
        model.addAttribute("maihost","http://mail." + StringUtils.substringAfter(memberInfo[1],"@"));
        AppContext.removeAttribute(token);
        return "/forget/step3";
    }

    /**
     * 发送手机验证码
     * @param token
     * @return
     */
    @RequestMapping(value = "/sendMobile", method = RequestMethod.POST)
    public String sendToMobile(String token, HttpServletResponse response){
        Object obj = AppContext.getSessionAttr(token);
        if(obj == null){
            return ResponseUtils.renderJSON(Message.error("手机验证发送失败"), response);
        }
        String[] memberInfo = (String[]) obj;

        ValueOperations<String, String> vo = redisTemplate.opsForValue();
        String key = REDIS_FORGET_SMS_PREFIX + memberInfo[2];
        long expiredTime = redisTemplate.getExpire(key);
        if(expiredTime > SMS_RESEND_TIME){
            return ResponseUtils.renderJSON(Message.error("请不要频繁发送验证码"), response);
        }

        JSONObject codeInfo = JSONObject.parseObject(memberHessian.sendMobileCaptcha(memberInfo[2], AppContext.getRemoteIp(), Boolean.TRUE, Long.valueOf(memberInfo[0]), 2));
        vo.set(key, codeInfo.getString("validateCode"), codeInfo.getLong("expired"), TimeUnit.MILLISECONDS);
        return ResponseUtils.renderJSON(successMessage, response);
    }

    /**
     * 验证手机验证码
     * @param code 手机验证码
     * @return
     */
    @Validations(
            requiredStrings = {
                    @RequiredStringValidator(fieldName="code",message="手机验证码错误"),
                    @RequiredStringValidator(fieldName="captchaId",message="验证码错误"),
                    @RequiredStringValidator(fieldName="captcha",message="验证码错误"),
                    @RequiredStringValidator(fieldName="token",message="手机验证失败")
            }
    )
    @RequestMapping(value="/verifyMobileCode", method=RequestMethod.POST)
    public String validateCode(String captchaId, String captcha, String token,
                               String code, HttpServletResponse response, Model model){
        if (!captchaService.isValid(captchaId, captcha)) {
            throw new NoticeException("验证码错误");
        }
        Object obj = AppContext.getSessionAttr(token);
        if(obj == null){
            throw new NoticeException("手机验证失败");
        }
        String[] memberInfo = (String[]) obj;
        Long memberId = Long.valueOf(memberInfo[0]);

        ValueOperations<String, String> vo = redisTemplate.opsForValue();

        String validateCode = vo.get(REDIS_FORGET_SMS_PREFIX + memberInfo[2]);
        if(StringUtils.isBlank(validateCode)){
            throw new NoticeException("验证码已失效");
        }
        if(!validateCode.equals(code)){
            throw new NoticeException("短信验证码不正确");
        }
        token = SerialNumberUtil.buildTokenSn();
        AppContext.setSessionAttr(token, memberId);
        return ResponseUtils.renderJSON(Message.success(token), response);
    }

    /**
     * 跳转到重置密码
     * @param token
     * @param model
     * @return
     */
    @RequestMapping(value = "/reset", method = RequestMethod.GET)
    public String reset(String token, Model model){
        Object obj = AppContext.getSessionAttr(token);
        if(obj == null){
            return "redirect:index.jhtml";
        }
        model.addAttribute("token", token);
        return "/forget/reset";
    }

    /**
     * 重置密码
     * @param token
     * @param password
     * @param model
     * @return
     */
    @RequestMapping(value = "/reset", method = RequestMethod.POST)
    public String reset(String token, String password,
                        final RedirectAttributes redirectAttributes,Model model){
        Object obj = AppContext.getSessionAttr(token);
        if(obj == null && !(obj instanceof Long)){
            return "redirect:index.jhtml";
        }
        Long memberId = (Long) obj;
        String error = memberHessian.resetPwd(memberId, password);
        if(StringUtils.isNotBlank(error)){
            redirectAttributes.addFlashAttribute("error",error);
            return "redirect:reset.jhtml?token="+token;
        }
        AppContext.removeAttribute(token);
        return "redirect:step4.jhtml";
    }

    /**
     * 完成设置
     * @return
     */
    @RequestMapping(value = "/step4", method = RequestMethod.GET)
    public String step4(){
        return "/forget/step4";
    }

}
